package simulation;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import domain.Car;
import domain.CrossRoad;
import domain.Road;
import domain.TrafficInfrastructure.TrafficObserver;

public class TrafficInfrastructureManager implements TrafficObserver {
	private Collection<Road> roads = new ArrayList<Road>();
	private Collection<CrossRoad> crossroads = new ArrayList<CrossRoad>();
	
	/* roads */
	public Collection<Road> getAllRoads(){
		return roads;
	}
	
	public void addRoad(Road road) {
		roads.add(road);
		road.subscribeTrafficObserver(this);
		notifyObservers();
	}
	
	public void removeRoad(Road road) {
		road.unsubscribeTrafficObserver(this);
		roads.remove(road);
		notifyObservers();
	}
	
	/* crossroads*/
	
	public Collection<CrossRoad> getAllCrossRoads() {
		return crossroads;
	}
	
	public void addCrossRoad(CrossRoad crossroad){
		crossroad.subscribeTrafficObserver(this);
		crossroads.add(crossroad);
		notifyObservers();
	}
	
	public void removeCrossRoad(CrossRoad crossroad) {
		crossroad.unsubscribeTrafficObserver(this);
		crossroads.remove(crossroad);
		notifyObservers();
	}
	
	/* cars*/
	
	public Collection<Car> getAllCars() {
		return getCars();
	}
	
	public void addCar(Car car){
		getCars().add(car);
	}
	
	public void removeCar(Car car) {
		getCars().remove(car);
	}
	
	public Car getCar(String label) {
		for(Car car : getCars()) {
			if(car.getId().equals(label)) {
				return car;
			}
		}
		return null;
	}
	
	private Collection<Car> getCars() {
		Collection<Car> thecars = new ArrayList<Car>(cars);
		for(Car car : thecars) {
			if(car.getPosition() == null) cars.remove(car);
		}
		return cars;
	}
	
	private Collection<Car> cars = new ArrayList<Car>();
	
	/* observers */
	
	public interface TrafficChangeObserver {
		public void notifyTrafficChange();
	}
	
	public void subscribeTrafficChangeObserver(TrafficChangeObserver obs) {
		observers.add(obs);
	}
	
	public void unsubscribeTrafficChangeObserver(TrafficChangeObserver obs) {
		observers.remove(obs);
	}
	
	private void notifyObservers() {
		for(TrafficChangeObserver obs : observers) {
			obs.notifyTrafficChange();
		}
	}
	
	private Set<TrafficChangeObserver> observers = new HashSet<TrafficChangeObserver>();

	/* subject van roads, crossroads */
	public void notifyTrafficChange() {
		notifyObservers();
	}
	

}
